// TCPSocketServer.cpp

#include "stdafx.h"
#include "TCPSocketServer.h"
#include "FrameBufferQueue.h"

TCPSocketServer::TCPSocketServer(void)
{
    m_socketTCP = 0;
    m_socketConnect = 0;
    m_pOwner = NULL;
    m_OnTCPError = NULL;
    m_OnTCPRecv = NULL;
    m_recvBuf = NULL;
    m_fbqBuf = new FrameBufferQueue(20);
}

TCPSocketServer::~TCPSocketServer(void)
{
    if (m_recvBuf)
    {
        delete m_recvBuf;

        m_recvBuf = NULL;
    }

    if (m_fbqBuf)
    {
        m_fbqBuf->Empty();

        delete m_fbqBuf;

        m_fbqBuf = NULL;
    }
}

DWORD TCPSocketServer::OpenTCP(void* pOwner, std::string strServerHost, int serverPort)
{
    if (pOwner == nullptr)
    {
        return -1;
    }
    m_pOwner = pOwner;

    WSADATA wsa;
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    {
        return -2;
    }

    m_socketTCP = socket(AF_INET, SOCK_STREAM, 0);

    if (m_socketTCP == INVALID_SOCKET)
    {
        return -3;
    }

    m_sockaddrin.sin_family = AF_INET;
    m_sockaddrin.sin_port = htons(serverPort);
    m_sockaddrin.sin_addr.S_un.S_addr = inet_addr(strServerHost.c_str());

    if (bind(m_socketTCP, (SOCKADDR*)&m_sockaddrin, sizeof(m_sockaddrin)) == SOCKET_ERROR)
    {
        return -4;
    }

    if (listen(m_socketTCP, SOMAXCONN) == SOCKET_ERROR)
    {
        return -5;
    }

    m_hExitThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    _beginthreadex(NULL, 0, AcceptThread, (LPVOID)this, 0, NULL);

    return 1;
}

DWORD TCPSocketServer::CloseTCP(void)
{
    SetEvent(m_hExitThreadEvent);

    Sleep(1000);

    CloseHandle(m_hExitThreadEvent);

    if (closesocket(m_socketTCP) == SOCKET_ERROR)
    {
        return -1;
    }

    if (WSACleanup() == SOCKET_ERROR)
    {
        return -2;
    }

    return 1;
}

UINT TCPSocketServer::AcceptThread(LPVOID lParam)
{
    TCPSocketServer* pSocket = (TCPSocketServer*)lParam;

    int addrlen = sizeof(pSocket->m_sockaddrin);

    pSocket->m_socketConnect = accept(pSocket->m_socketTCP, (SOCKADDR*)&pSocket->m_sockaddrin, &addrlen);

    if (pSocket->m_socketConnect != INVALID_SOCKET)
    {
        _beginthreadex(NULL, 0, ReceiveThread, lParam, 0, NULL);
    }

    return 0;
}

UINT TCPSocketServer::ReceiveThread(LPVOID lparam)
{
    TCPSocketServer* pSocket = (TCPSocketServer*)lparam;
    int recvLen = 0;
    int leftLen = 5;
    char* save;

    int nZero = 0;

    setsockopt(pSocket->m_socketConnect, SOL_SOCKET, SO_RCVBUF, (char*)&nZero, sizeof(nZero));

    while (TRUE)
    {
        if (WaitForSingleObject(pSocket->m_hExitThreadEvent, 0) == WAIT_OBJECT_0)
        {
            break;
        }

        pSocket->m_recvBuf = new char[5];

        ZeroMemory(pSocket->m_recvBuf, 5);

        save = pSocket->m_recvBuf;

        while (leftLen > 0)
        {
            recvLen = recv(pSocket->m_socketConnect, save += recvLen, leftLen, 0);

            //pSocket->m_OnTCPRecv(pSocket->m_pOwner, pSocket->m_recvBuf, recvLen, (SOCKADDR_IN*)&pSocket->m_sockaddrin);

            leftLen -= recvLen;
        }

        recvLen = 0;
        leftLen = 5;

        if (recvLen == 5)
        {
            pSocket->SaveData((LPVOID*)pSocket->m_recvBuf);

            if (pSocket->m_OnTCPRecv)
            {
                pSocket->m_OnTCPRecv(pSocket->m_pOwner, pSocket->m_recvBuf, recvLen, (SOCKADDR_IN*)&pSocket->m_sockaddrin);
            }
        }

        pSocket->m_recvBuf = NULL;
    }

    return 0;
}

DWORD TCPSocketServer::SaveData(LPVOID* data)
{
    if (!m_fbqBuf)
    {
        m_fbqBuf = new FrameBufferQueue(20);
    }

    m_fbqBuf->EnQueue(data);

    if (m_fbqBuf->GetSize() > 5)
    {
        if (m_OnTCPCall)
        {

        }
    }

    return 1;
}

DWORD TCPSocketServer::GetData(LPVOID* data)
{
    if (m_fbqBuf->IsEmpty())
    {
        return 0;
    }

    *data = m_fbqBuf->DeQueue();

    return 1;
}
